﻿using Compass.Wasm.Shared.Purchases;
using Compass.Wpf.ApiServices.Purchases;
using Microsoft.Win32;
using OfficeOpenXml;
using System.Collections.Generic;
using System.IO;
using Compass.Wasm.Shared.Categories;
using Compass.Wasm.Shared.Extensions;
using Compass.Wasm.Shared.Wms;

namespace Compass.Wpf.ViewModels.Purchases;

public class NavItemToolViewModel : NavigationViewModel
{
    #region ctor
    private readonly INavItemService _navItemService;
    private readonly INavInvReportGroupService _navInvReportGroupService;
    public NavItemToolViewModel(IContainerProvider provider) : base(provider)
    {
        _navItemService = provider.Resolve<INavItemService>();
        _navInvReportGroupService = provider.Resolve<INavInvReportGroupService>();

        ExcelPackage.LicenseContext = LicenseContext.NonCommercial;

        BrowseFileCommand = new DelegateCommand<string>(BrowseFile);
        ReadInvReportGroupCommand = new DelegateCommand(ReadInvReportGroup);
        SaveInvReportGroupCommand = new DelegateCommand(SaveInvReportGroup);
        ReadItemWithGroupCommand = new DelegateCommand(ReadItemWithGroup);
        ReadItemListCommand = new DelegateCommand(ReadItemList);
        AddItemCommand = new DelegateCommand(AddItem);
        UpdateItemCommand = new DelegateCommand<NavItemDto>(UpdateItem);
        DeleteItemCommand = new DelegateCommand<NavItemDto>(DeleteItem);
        SaveItemCommand = new DelegateCommand(SaveItem);
        ExportExcelCommand = new DelegateCommand(ExportExcel);
        UpdateRoles = "admin,pur";
        GroupRoles = "admin";
    }
    
    private string groupRoles;
    public string GroupRoles
    {
        get => groupRoles;
        set { groupRoles = value; RaisePropertyChanged(); }
    }
    private string updateRoles;
    public string UpdateRoles
    {
        get => updateRoles;
        set { updateRoles = value; RaisePropertyChanged(); }
    }
    public DelegateCommand<string> BrowseFileCommand { get; }
    public DelegateCommand ReadInvReportGroupCommand { get; }
    public DelegateCommand SaveInvReportGroupCommand { get; }
    public DelegateCommand ReadItemWithGroupCommand { get; }
    public DelegateCommand ReadItemListCommand { get; }
    public DelegateCommand AddItemCommand { get; }
    public DelegateCommand<NavItemDto> UpdateItemCommand { get; }
    public DelegateCommand<NavItemDto> DeleteItemCommand { get; }
    public DelegateCommand SaveItemCommand { get; }


    public DelegateCommand ExportExcelCommand { get; }
    #endregion

    #region 右侧展开栏属性
    private bool isRightDrawerOpen;
    /// <summary>
    /// 右侧窗口是否展开
    /// </summary>
    public bool IsRightDrawerOpen
    {
        get => isRightDrawerOpen;
        set { isRightDrawerOpen = value; RaisePropertyChanged(); }
    }
    private string rightDrawerTitle = null!;
    public string RightDrawerTitle
    {
        get => rightDrawerTitle;
        set { rightDrawerTitle = value; RaisePropertyChanged(); }
    }
    #endregion

    #region 属性
    private bool isEnable = true;
    public bool IsEnable
    {
        get => isEnable;
        set { isEnable = value; RaisePropertyChanged(); }
    }
    private string itemWithGroupPath;
    public string ItemWithGroupPath
    {
        get => itemWithGroupPath;
        set { itemWithGroupPath = value; RaisePropertyChanged(); }
    }
    private string itemListPath;
    public string ItemListPath
    {
        get => itemListPath;
        set { itemListPath = value; RaisePropertyChanged(); }
    }
    private string invReportGroupPath;
    public string InvReportGroupPath
    {
        get => invReportGroupPath;
        set { invReportGroupPath = value; RaisePropertyChanged(); }
    }

    private string[] units = null!;
    public string[] Units
    {
        get => units;
        set { units = value; RaisePropertyChanged(); }
    }
    private string[] sbus = null!;
    public string[] Sbus
    {
        get => sbus;
        set { sbus = value; RaisePropertyChanged(); }
    }
    private string[] groups = null!;
    public string[] Groups
    {
        get => groups;
        set { groups = value; RaisePropertyChanged(); }
    }

    private string search;
    /// <summary>
    /// 搜索条件属性
    /// </summary>
    public string Search
    {
        get => search;
        set
        {
            search = value;
            RaisePropertyChanged();
            Filter();
        }
    }
    private bool fsShare = true;
    public bool FsShare
    {
        get => fsShare;
        set
        {
            fsShare = value;
            RaisePropertyChanged();
            Filter();
        }
    }

    private NavItemDto navItemDto;
    public NavItemDto NavItemDto
    {
        get => navItemDto;
        set { navItemDto = value; RaisePropertyChanged(); }
    }
    public ObservableRangeCollection<NavItemDto> FSItemList { get; } = new();
    public ObservableRangeCollection<NavItemDto> FilterFSItemList { get; } = new();
    #endregion

    #region 浏览文件
    private void BrowseFile(string obj)
    {
        var dialog = new OpenFileDialog
        {
            Filter = "Excel|*.xlsx",
            InitialDirectory = Environment.GetFolderPath(System.Environment.SpecialFolder.DesktopDirectory)
        };

        if (dialog.ShowDialog() != true) return;
        switch (obj)
        {
            case "ItemWithGroupPath":
                ItemWithGroupPath=dialog.FileName;
                break;
            case "ItemListPath":
                ItemListPath = dialog.FileName;
                break;
            case "InvReportGroupPath":
                InvReportGroupPath=dialog.FileName;
                break;

        }
    }
    #endregion

    #region 批量读取InvReportGroup时使用
    private async void ReadInvReportGroup()
    {
        IsEnable = false;
        await Task.Delay(100);
        if (string.IsNullOrEmpty(InvReportGroupPath))
        {
            Aggregator.SendMessage("请选择InvReportGroup表格地址！");
            IsEnable = true;
            return;
        }

        ChangeInvReportGroupTitle(InvReportGroupPath);

        var invReportGroupStrings = InvReportGroupPath.ReadFromExcel<List<NavInvReportGroupString>>();

        //将String值转化成double和bool值
        //只需要Number是1或2的
        var invReportGroupDtos = invReportGroupStrings
            .Select(x => new NavInvReportGroupDto
                            {
                                //使用s最后一天
                YearMonth = x.YearMonth.ToDateTime().AddDays(1-x.YearMonth.ToDateTime().Day).AddMonths(1).AddDays(-1),
                                Group = x.Group.ToUpper().ToEnum<Group_e>(),
                                InvValue =Math.Round(x.InvValue.ToDouble(), 2) 
                            })
                            .ToList();

        //遍历，没有就添加，有就更新
        foreach (var item in invReportGroupDtos)
        {
            var exist = await _navInvReportGroupService.GetSingleByMonthAndGroupAsync(item.YearMonth,item.Group);
            if (exist.Status)
            {
                await _navInvReportGroupService.UpdateAsync(exist.Result.Id.Value, item);
            }
            else
            {
                await _navInvReportGroupService.AddAsync(item);
            }
        }
        GetDataAsync();
        Aggregator.SendMessage("已读取InvReportGroup表格信息并更新到数据库！");
        IsEnable = true;
    }

    private void ChangeInvReportGroupTitle(string path)
    {
        using var package = new ExcelPackage(path);

        //修改表头,方便后面读取数据
        //Epplus的所有行列数都是以1开始的
        var worksheet = package.Workbook.Worksheets[0];//第一张表格
        //直接指定单元格进行赋值
        worksheet.Cells["A1"].Value = "YearMonth";
        worksheet.Cells["B1"].Value = "Group";
        worksheet.Cells["C1"].Value = "InvValue";
        // 保存Excel文件
        package.Save();
    }
    #endregion

    #region 每月保存物料类别库存统计数据SaveInvReportGroup
    private async void SaveInvReportGroup()
    {
        IsEnable = false;
        var lastMonth = DateTime.Today.AddDays(1 - DateTime.Today.Day).AddDays(-1);
        
        //保存询问
        var dialogResult = await DialogHost.Question("保存确认", $"确认要保存{lastMonth.Year}年{lastMonth.Month}月的物料类别库存统计数据吗?");
        if (dialogResult.Result != ButtonResult.OK)
        {
            IsEnable = true;
            return;
        }

        await Task.Delay(100);
        //筛选FS，且只留下Material
        var mtlItems = FSItemList.Where(x =>
            (!FsShare || x.Sbu is Sbu_e.FS or Sbu_e.SHARE)&& (x.Number[..1]=="1" || x.Number[..1]=="2"));
        
        var dtos = mtlItems.GroupBy(x => x.Group).Select(x => new NavInvReportGroupDto
        {
            YearMonth = lastMonth,
            Group = x.Key,
            InvValue = Math.Round(x.Sum(y => y.Inventory*y.UnitCost),2)
        });

        foreach (var item in dtos)
        {
            var exist = await _navInvReportGroupService.GetSingleByMonthAndGroupAsync(item.YearMonth, item.Group);
            if (exist.Status)
            {
                await _navInvReportGroupService.UpdateAsync(exist.Result.Id.Value, item);
            }
            else
            {
                await _navInvReportGroupService.AddAsync(item);
            }
        }

        Aggregator.SendMessage("保存InvReportGroup物料类别库存统计数据到数据库！");
        IsEnable = true;


    }
    #endregion


    #region 批量更新Group时使用
    private async void ReadItemWithGroup()
    {
        IsEnable = false;
        await Task.Delay(100);
        if (string.IsNullOrEmpty(ItemWithGroupPath))
        {
            Aggregator.SendMessage("请选择ItemWithGroup表格地址！");
            IsEnable = true;
            return;
        }

        ChangeItemWithGroupTitle(ItemWithGroupPath);

        var navItemStrings = ItemWithGroupPath.ReadFromExcel<List<NavItemString>>();

        //将String值转化成double和bool值
        //只需要Number是1或2的
        var navItemDtos = navItemStrings
            .Where(x => x.Number[..1]=="1" ||
                        x.Number[..1]=="2"||
                        x.Number[..1]=="5"||
                        x.Number[..1]=="7")
                            .Select(x => new NavItemDto
                            {
                                Number = x.Number,
                                Description = x.Description,
                                EnDescription = x.EnDescription,
                                Inventory = x.Inventory.ToDouble(),
                                SafetyStock = x.SafetyStock.ToDouble(),
                                OpenPo = x.OpenPo.ToInt(),
                                Sbu = x.Sbu.ToEnum<Sbu_e>(),
                                Unit = x.Unit.ToEnum<Unit_e>(),
                                UnitCost = x.UnitCost.ToDouble(),
                                LastCost = x.LastCost.ToDouble(),
                                UnitPrice = x.UnitPrice.ToDouble(),
                                Vendor = x.Vendor,
                                Consumable = x.Consumable.ToBool(),
                                Group = x.Group.ToUpper().ToEnum<Group_e>()
                            })
                            .ToList();

        //遍历，没有就添加，有就更新
        foreach (var item in navItemDtos)
        {
            var exist = await _navItemService.GetSingleByNumberAsync(item.Number);
            if (exist.Status)
            {
                await _navItemService.UpdateAsync(exist.Result.Id.Value, item);
            }
            else
            {
                await _navItemService.AddAsync(item);
            }
        }
        GetDataAsync();
        Aggregator.SendMessage("已读取ItemWithGroup表格信息并更新到数据库！");
        IsEnable = true;
    }

    private void ChangeItemWithGroupTitle(string path)
    {
        using var package = new ExcelPackage(path);

        //修改表头,方便后面读取数据
        //Epplus的所有行列数都是以1开始的
        var worksheet = package.Workbook.Worksheets[0];//第一张表格
        //直接指定单元格进行赋值
        worksheet.Cells["A1"].Value = "Number";
        worksheet.Cells["B1"].Value = "Description";
        worksheet.Cells["C1"].Value = "EnDescription";
        worksheet.Cells["D1"].Value = "Inventory";
        worksheet.Cells["E1"].Value = "SafetyStock";
        worksheet.Cells["F1"].Value = "OpenPo";
        worksheet.Cells["G1"].Value = "Sbu";
        worksheet.Cells["H1"].Value = "Unit";
        worksheet.Cells["I1"].Value = "UnitCost";
        worksheet.Cells["J1"].Value = "LastCost";
        worksheet.Cells["K1"].Value = "UnitPrice";
        worksheet.Cells["L1"].Value = "Vendor";
        worksheet.Cells["M1"].Value = "Consumable";
        worksheet.Cells["N1"].Value = "Group";
        // 保存Excel文件
        package.Save();
    }
    #endregion

    #region 批量更新数据时使用
    private async void ReadItemList()
    {
        IsEnable = false;
        await Task.Delay(100);
        if (string.IsNullOrEmpty(ItemListPath))
        {
            Aggregator.SendMessage("请选择ItemList表格地址！");
            IsEnable = true;
            return;
        }

        ChangeItemListTitle(ItemListPath);

        var navItemStrings = ItemListPath.ReadFromExcel<List<NavItemString>>();

        //将String值转化成double和bool值
        var navItemDtos = navItemStrings
            .Where(x => x.Number[..1]=="1" ||
                        x.Number[..1]=="2"||
                        x.Number[..1]=="5"||
                        x.Number[..1]=="7")
            .Select(x => new NavItemDto
            {
                Number = x.Number,
                Description = x.Description,
                EnDescription = x.EnDescription,
                Inventory =Math.Round(x.Inventory.ToDouble(),2),
                SafetyStock = x.SafetyStock.ToDouble(),
                OpenPo = x.OpenPo.ToInt(),
                Sbu = x.Sbu.ToEnum<Sbu_e>(),
                Unit = x.Unit.ToEnum<Unit_e>(),
                UnitCost = Math.Round(x.UnitCost.ToDouble(),2),
                LastCost = Math.Round(x.LastCost.ToDouble(), 2),
                UnitPrice = Math.Round(x.UnitPrice.ToDouble(), 2),
                Vendor = x.Vendor,
                Consumable = x.Consumable.ToBool()
            })
            .ToList();

        //遍历，没有就添加，有就更新
        foreach (var item in navItemDtos)
        {
            var exist = await _navItemService.GetSingleByNumberAsync(item.Number);
            if (exist.Status)
            {
                //不能更新group，只能更新部分内容
                var dto = exist.Result;
                dto.Description= item.Description;
                dto.EnDescription = item.EnDescription;
                dto.Inventory = item.Inventory;
                dto.SafetyStock = item.SafetyStock;
                dto.OpenPo=item.OpenPo;
                dto.Sbu = item.Sbu;
                dto.Unit = item.Unit;
                dto.UnitCost = item.UnitCost;
                dto.LastCost = item.LastCost;
                dto.UnitPrice = item.UnitPrice;
                dto.Vendor = item.Vendor;
                dto.Consumable = item.Consumable;
                await _navItemService.UpdateAsync(dto.Id.Value, dto);
            }
            else
            {
                await _navItemService.AddAsync(item);
                Aggregator.SendMessage($"注意，新增了物料{item.Number},请手动修改分类！");
            }
        }
        GetDataAsync();
        Aggregator.SendMessage("已读取ItemList表格信息并更新到数据库！");
        IsEnable = true;
    }

    private void ChangeItemListTitle(string path)
    {
        using var package = new ExcelPackage(path);

        //修改表头,方便后面读取数据
        //Epplus的所有行列数都是以1开始的
        var worksheet = package.Workbook.Worksheets[0];//第一张表格
        //直接指定单元格进行赋值
        worksheet.Cells["A1"].Value = "Number";
        worksheet.Cells["B1"].Value = "Description";
        worksheet.Cells["C1"].Value = "EnDescription";
        worksheet.Cells["D1"].Value = "Inventory";
        worksheet.Cells["E1"].Value = "SafetyStock";
        worksheet.Cells["F1"].Value = "OpenPo";
        worksheet.Cells["J1"].Value = "Sbu";
        worksheet.Cells["L1"].Value = "Unit";
        worksheet.Cells["N1"].Value = "UnitCost";
        worksheet.Cells["O1"].Value = "LastCost";
        worksheet.Cells["P1"].Value = "UnitPrice";
        worksheet.Cells["Q1"].Value = "Vendor";
        worksheet.Cells["AC1"].Value = "Consumable";
        // 保存Excel文件
        package.Save();
    }
    #endregion

    #region 手动新增和更改Item时使用
    private void AddItem()
    {
        NavItemDto=new NavItemDto();

        IsRightDrawerOpen = true;
        RightDrawerTitle = "添加Item";
    }

    private void UpdateItem(NavItemDto obj)
    {
        NavItemDto=obj;

        IsRightDrawerOpen = true;
        RightDrawerTitle = "修改Item";
    }

    private async void DeleteItem(NavItemDto obj)
    {
        //删除询问
        var dialogResult = await DialogHost.Question("删除确认", $"确认删除Item：{obj.Number}, {obj.Description} 吗?");
        if (dialogResult.Result != ButtonResult.OK) return;
        await _navItemService.DeleteAsync(obj.Id.Value);
        GetDataAsync();
    }

    private async void SaveItem()
    {
        //数据验证
        if (string.IsNullOrWhiteSpace(NavItemDto.Number))
        {
            //发送提示
            Aggregator.SendMessage("Number不能为空");
            return;
        }

        try
        {
            if (NavItemDto.Id != null && NavItemDto.Id.Value != Guid.Empty)
            {
                NavItemDto.Number =NavItemDto.Number.ToUpper();
                await _navItemService.UpdateAsync(NavItemDto.Id.Value, NavItemDto);
                Aggregator.SendMessage($"Item：{NavItemDto.Number}，{NavItemDto.Description}修改成功！");
                NavItemDto.Id=Guid.Empty;
            }
            else
            {
                NavItemDto.Number =NavItemDto.Number.ToUpper();
                var cargoResult = await _navItemService.GetSingleByNumberAsync(NavItemDto.Number);
                if (cargoResult.Status)
                {
                    Aggregator.SendMessage($"请不要重复添加，Item：{NavItemDto.Number}！");
                    return;
                }

                await _navItemService.AddAsync(NavItemDto);
                Aggregator.SendMessage($"Item：{NavItemDto.Number},{NavItemDto.Description}添加成功！");
                NavItemDto.Id=Guid.Empty;
            }
            IsRightDrawerOpen = false;
            GetDataAsync();
        }
        catch (Exception e)
        {
            //发送错误报告
            Aggregator.SendMessage(e.Message);
        }
    }
    #endregion

    #region 导出Excel
    private void ExportExcel()
    {
        IsEnable = false;
        var tableName = "ItemList";
        var tablePath = Path.Combine(System.Environment.GetFolderPath(System.Environment.SpecialFolder.DesktopDirectory), $"【Compass】{tableName}{DateTime.Now:yyyy-MM-dd-hh-mm-ss}.xlsx");

        if (FSItemList.Any())
        {
            var itemNoEnums = FSItemList.Select(x =>
                new NavItemNoEnum()
                {
                    Number = x.Number,
                    Description = x.Description,
                    EnDescription = x.EnDescription,
                    Inventory = x.Inventory,
                    SafetyStock = x.SafetyStock,
                    OpenPo=x.OpenPo,
                    Sbu = x.Sbu.ToString(),
                    Unit = x.Unit.ToString(),
                    UnitCost = x.UnitCost,
                    LastCost = x.LastCost,
                    UnitPrice = x.UnitPrice,
                    Vendor = x.Vendor,
                    Consumable = x.Consumable,
                    Group = x.Group.ToString()
                }
            );
            itemNoEnums.WriteExcel(tablePath, tableName);

            Aggregator.SendMessage("导出ItemList数据Excel到桌面完成！");
        }
        else
        {
            Aggregator.SendMessage("没有数据，不能导出Excel！");
        }
        IsEnable = true;
    }
    #endregion

    #region 筛选
    private void Filter()
    {
        FilterFSItemList.ReplaceRange(
            FSItemList.Where(x =>
                (!FsShare||x.Sbu is Sbu_e.FS or Sbu_e.SHARE)&&(
                string.IsNullOrEmpty(Search)||
                x.Number.Contains(Search, StringComparison.OrdinalIgnoreCase)||
                (!string.IsNullOrEmpty(x.Description)&&x.Description!.Contains(Search, StringComparison.OrdinalIgnoreCase)) ||
                (!string.IsNullOrEmpty(x.EnDescription)&&x.EnDescription!.Contains(Search, StringComparison.OrdinalIgnoreCase)) ||
                x.Group.ToString().ToUpper().Contains(Search.ToUpper(), StringComparison.OrdinalIgnoreCase) ||
                (!string.IsNullOrEmpty(x.Vendor)&&x.Vendor!.Contains(Search, StringComparison.OrdinalIgnoreCase)))
                ));
        //有的时候Remarks是null，导致调用Contains报错
    }
    #endregion

    #region 导航和初始化
    private void GetEnumNames()
    {
        //初始化一些枚举值
        Units=Enum.GetNames(typeof(Unit_e));
        Sbus=Enum.GetNames(typeof(Sbu_e));
        Groups=Enum.GetNames(typeof(Group_e));

    }

    private async void GetDataAsync()
    {

        var result = await _navItemService.GetAllAsync();
        if (result.Status)
        {
            FSItemList.ReplaceRange(result.Result);
        }
        Filter();
    }

    public override void OnNavigatedTo(NavigationContext navigationContext)
    {
        base.OnNavigatedTo(navigationContext);
        GetEnumNames();
        GetDataAsync();
    }
    #endregion
}